//
//  JRHttpRequestConstants.m
//  
//
//  Created by dingjiarui on 2021/7/26.
//

#import "JRHttpRequestConstants.h"

NSString * const JRHttpGlobalOpId = @"JRHttpRequestConstants_GlobalOpId";

@interface JRHttpRequestConstants ()

@property (nonatomic, strong) NSMapTable *fileRequestMapTable;

/** 请求、上传 下载的队列 */
@property (nonatomic, strong) NSMutableDictionary *operationQueueDicts;

@end

@implementation JRHttpRequestConstants

#pragma mark - instancetype
+ (instancetype)constants {
    
    static JRHttpRequestConstants *constants = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        constants = [[JRHttpRequestConstants alloc] initCustom];
    });
    
    return constants;
}

#pragma mark - Custom Public Methods

#pragma mark - 队列
#pragma mark 创建队列
- (nullable NSOperationQueue *)createOperationQueue:(NSString *)opId maxCount:(NSInteger)maxCount {
    
    if ([JRHttpRequestConstants JREmpty:opId]) {
        return nil;
    }

    NSOperationQueue *queue = [self.operationQueueDicts objectForKey:opId];
    if (queue == nil) {
        queue = [[NSOperationQueue alloc] init];
        [queue setMaxConcurrentOperationCount:maxCount];
        [self.operationQueueDicts setObject:queue forKey:opId];
    }
    return queue;

}

#pragma mark 获取线程
- (nullable NSOperation *)operationForKey:(NSString *)key opId:(NSString *)opId {
    if ([JRHttpRequestConstants JREmpty:key]) {
        return nil;
    }
    NSMutableDictionary *requestDict = [self _getFileRequestDictWithOpId:opId];
    return requestDict[key];
}

#pragma mark 添加线程到队列
- (void)addOperation:(NSOperation *)op key:(NSString *)key opId:(NSString *)opId {
    
    if (op && [op isKindOfClass:[NSOperation class]]) {
        NSOperationQueue *queue = [self _getOperationQueueWithOpId:opId];
        [queue addOperation:op];
    }
    
    if ([JRHttpRequestConstants JREmpty:key]) {
        return;
    }
    
    NSMutableDictionary *requestDict = [self _getFileRequestDictWithOpId:opId];
    [requestDict setObject:op forKey:key];

}


#pragma mark 清除线程
- (void)cancelOperationWithKey:(NSString *)key withOpId:(NSString *)opId completion:(void (^)(NSOperation * _Nonnull))completion {
    
    if (![JRHttpRequestConstants JREmpty:key]) {
        if (completion) {
            NSOperation *operation = [self operationForKey:key opId:opId];
            completion(operation);
            [operation cancel];
        }
        NSMutableDictionary *requestDict = [self _getFileRequestDictWithOpId:opId];
        [requestDict removeObjectForKey:key];
        if (requestDict.count == 0) {
            [self _removeFileRequestDictWithOpId:opId];
        }
    }

    NSOperationQueue *queue = [self _getOperationQueueWithOpId:opId];
    if (queue.operationCount == 0) {
        [self _removeOperationQueueForOpId:opId];
    }

}

#pragma mark 清除某队列
- (void)cancelAllOperationsWithOpId:(NSString *)opId completion:(void (^)(NSOperation * _Nonnull))completion {
    if (completion) {
        NSOperationQueue *queue = [self _getOperationQueueWithOpId:opId];
        for (NSOperation *operation in queue.operations) {
            completion(operation);
            [operation cancel];
        }
        [self _removeOperationQueueForOpId:opId];
    }
}

#pragma mark 清除所有队列的线程
- (void)cancelAllOperations:(void (^)(NSOperation * _Nonnull))completion {
    if (completion) {
        for (NSString *key in self.operationQueueDicts) {
            NSOperationQueue *queue = self.operationQueueDicts[key];
            for (NSOperation *operation in queue.operations) {
                completion(operation);
                [operation cancel];
            }
        }
    }
    [self.operationQueueDicts removeAllObjects];
    [self.fileRequestMapTable removeAllObjects];
}

#pragma mark - 网络请求
- (void)addOperationRequest:(NSOperation *)op {
    [self addOperationRequest:op key:nil];
}

- (void)addOperationRequest:(NSOperation *)op key:(nullable NSString *)key {
    [self addOperationRequest:op key:key opId:nil];
}

- (void)addOperationRequest:(NSOperation *)op key:(nullable NSString *)key opId:(nullable NSString *)opId {
    if (op && [op isKindOfClass:[NSOperation class]]) {
        [self addOperation:op key:key opId:opId];
    }
}

#pragma mark - Private Methods
- (instancetype)initCustom {
    self = [super init];
    if (self) {
        
        if (_fileRequestMapTable == nil) {
            _fileRequestMapTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableStrongMemory];
        }
        
        if (_operationQueueDicts == nil) {
            _operationQueueDicts = [NSMutableDictionary dictionary];
        }

    }
    
    return self;
}

#pragma mark 获取线程字典
/// 获取线程字典
/// @param opId 队列标识 （opId 为nil，拿默认队列）
- (NSMutableDictionary *)_getFileRequestDictWithOpId:(nullable NSString *)opId {
    
    NSString *key = [JRHttpRequestConstants JREmpty:opId] ? JRHttpGlobalOpId : opId;
    NSMutableDictionary *fileRequestDict = [self.fileRequestMapTable objectForKey:key];
    if (fileRequestDict == nil) {
        fileRequestDict = [[NSMutableDictionary alloc]init];
        [self.fileRequestMapTable setObject:fileRequestDict forKey:key];
    }
    return fileRequestDict;
    
}

#pragma mark 删除线程字典
/// 删除线程字典
/// @param opId opId 队列标识 （opId 为nil，拿默认队列）
- (void)_removeFileRequestDictWithOpId:(nullable NSString *)opId {
    
    NSString *key = [JRHttpRequestConstants JREmpty:opId] ? JRHttpGlobalOpId : opId;
    [self.fileRequestMapTable removeObjectForKey:opId];
    
}

#pragma mark 创建队列

/// 创建默认队列 （最大线程数为10）
/// @param opId 队列标识
- (nullable NSOperationQueue *)_createDefaultOperationQueue:(NSString *)opId {
    return [self createOperationQueue:opId maxCount:10];
}

#pragma mark 获取队列线程
- (NSOperationQueue *)_getOperationQueueWithOpId:(nullable NSString *)opId
{
    return [self _createDefaultOperationQueue:([JRHttpRequestConstants JREmpty:opId] ? JRHttpGlobalOpId : opId)];
}

#pragma mark 删除队列线程
- (void)_removeOperationQueueForOpId:(nullable NSString *)opId
{
    [self.operationQueueDicts removeObjectForKey:([JRHttpRequestConstants JREmpty:opId] ? JRHttpGlobalOpId : opId)];
}

+ (BOOL)JREmpty:(nullable NSString *)str {
    if ([str isKindOfClass:[NSString class]]) {
        /// 去掉空格，回车
        NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
        NSString *trimmedStr = [str stringByTrimmingCharactersInSet:set];
        if (trimmedStr.length) {
            return NO;
        }
    }
    
    return YES;
}
@end
